package com.example.forum.services.impl;

import cn.hutool.json.JSONUtil;
import com.example.forum.entity.Article;
import com.example.forum.entity.User;
import com.example.forum.exception.CustomException;
import com.example.forum.mapper.ArticleMapper;
import com.example.forum.mapper.BoardMapper;
import com.example.forum.mapper.UserMapper;
import com.example.forum.services.IArticleService;
import com.example.forum.utils.StringUtil;
import com.example.forum.vo.ArticleDetailVO;
import com.example.forum.vo.ArticleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.example.forum.constant.MessageConstant.*;

@Service
public class ArticleServiceImpl implements IArticleService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private BoardServiceImpl boardService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private BoardMapper boardMapper;

    @Autowired
    private UserMapper userMapper;

    /**
     * 创建文章
     *
     * @param article
     */
    @Transactional
    public void create(Article article) throws CustomException {
        // 初始化默认值
        article.setVisitCount(0);
        article.setReplyCount(0);
        article.setLikeCount(0);
        article.setDeleteState(0);
        article.setState(0);

        Date now = new Date();
        article.setCreateTime(now);
        article.setUpdateTime(now);

        // 清除缓存
        redisTemplate.delete("article: " + article.getBoardId());
        redisTemplate.delete("article: " + null);

        // 保存文章
        Integer count = articleMapper.create(article);
        if (count != 1) {
            throw new CustomException(ADD_FAILED);
        }
        // 更新板块文章数量
        Integer row = boardService.updateArticleCount(article.getBoardId());
        if (row != 1) {
            throw new CustomException(ADD_FAILED);
        }
        // 更新用户文章数量
        Integer user_row = userService.updateArticleCount(article.getUserId());
        if (user_row != 1) {
            throw new CustomException(ADD_FAILED);
        }
    }

    /**
     * 获取所有文章
     *
     * @param boardId (id可选)
     * @return
     */
    public List<ArticleVO> getAllArticle(Long boardId) {
        String key = "article: " + boardId;
        List<ArticleVO> articleVOList = new ArrayList<>();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            List<String> range = redisTemplate.opsForList().range(key, 0, -1);
            for (String s : range) {
                articleVOList.add(JSONUtil.toBean(s, ArticleVO.class));
            }
            return articleVOList;
        }
        articleVOList = articleMapper.getAllArticle(boardId);
        articleVOList.forEach(articleVO -> {
            // 将对象转为json字符串
            String jsonStr = JSONUtil.toJsonStr(articleVO);
            redisTemplate.opsForList().leftPush(key, jsonStr);
        });
        return articleVOList;
    }

    /**
     * 根据板块id获取所有文章
     *
     * @param boardId
     * @return
     */
    public List<ArticleVO> getAllByBoardId(Long boardId) {
        String key = "article: " + boardId;
        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            List<String> range = redisTemplate.opsForList().range(key, 0, -1);
            List<ArticleVO> articleVOList = new ArrayList<>();
            for (String s : range) {
                articleVOList.add(JSONUtil.toBean(s, ArticleVO.class));
            }
            return articleVOList;
        }
        List<ArticleVO> allArticle = articleMapper.getAllArticle(boardId);
        if (!allArticle.isEmpty()) {
            allArticle.forEach(articleVO -> {
                // 将对象转为json字符串
                String jsonStr = JSONUtil.toJsonStr(articleVO);
                redisTemplate.opsForList().leftPush(key, jsonStr);
            });
        }
        return allArticle;
    }

    /**
     * 根据id获取文章内容
     *
     * @param articleId
     * @return
     */
    public ArticleDetailVO getById(Long articleId) throws CustomException {

        // 根据id获取文章内容
        ArticleDetailVO articleDetailVO = articleMapper.getById(articleId);
        if (articleDetailVO == null) {
            throw new CustomException(ARTICLE_NOT_EXISTS);
        }
        // 更新帖子访问量
        articleMapper.updateVisitCount(articleId);

        articleDetailVO.setVisitCount(articleDetailVO.getVisitCount() + 1);
        return articleDetailVO;

    }

    /**
     * 修改文章
     *
     * @param id
     * @param title
     * @param content
     */
    public void modify(Long id, String title, String content) throws CustomException {
        if (id == null || StringUtil.isEmpty(title) || StringUtil.isEmpty(content)) {
            throw new CustomException("参数不能为空");
        }
        redisTemplate.delete("article: " + articleMapper.getByIdArticle(id).getBoardId());
        redisTemplate.delete("article: " + null);
        articleMapper.modify(id, title, content);
    }

    /**
     * 根据id获取文章
     *
     * @param id
     * @return
     */
    public Article getByIdArticle(Long id) {
        return articleMapper.getByIdArticle(id);
    }

    /**
     * 点赞
     *
     * @param id
     * @param user
     * @return
     */
    public boolean thumbsUp(Long id, User user) throws CustomException {
        // 参数校验
        if (id == null) {
            throw new CustomException(PARAMETER_VERIFICATION_FAILED);
        }
        Article article = articleMapper.getByIdArticle(id);
        // 帖子状态校验
        if (article == null) {
            throw new CustomException(ARTICLE_NOT_EXISTS);
        }
        if (article.getDeleteState() == 1) {
            throw new CustomException(ARTICLE_DELETE_FAILED);
        }
        boolean isThumbsUp = true;
        // 缓存校验
        String key = "thumbsUp:" + "article: " + id + ":" + user.getId();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            redisTemplate.delete(key);
            articleMapper.thumbsOf(id);
            return !isThumbsUp;
        } else {
            redisTemplate.opsForValue().set(key, "1");
            articleMapper.thumbsUp(id);
            return isThumbsUp;
        }
    }

    /**
     * 删除文章
     *
     * @param id
     * @param boardId
     */
    @Transactional
    public void delete(Long id, Long userId, Long boardId) throws CustomException {
        // 参数校验
        if (id == null) {
            throw new CustomException(PARAMETER_VERIFICATION_FAILED);
        }

        // 删除缓存
        redisTemplate.delete("article: " + articleMapper.getByIdArticle(id).getBoardId());
        redisTemplate.delete("article: " + null);

        // 删除文章
        Integer a_delete = articleMapper.delete(id);
        if (a_delete != 1) {
            throw new CustomException(DELETE_FAILED);
        }

        // 更新板块文章数量
        Integer b_delete = boardMapper.deleteArticleCount(boardId);
        if (b_delete != 1) {
            throw new CustomException(DELETE_FAILED);
        }

        // 更新用户文章数量
        Integer u_delete = userMapper.deleteArticleCount(userId);
        if (u_delete != 1) {
            throw new CustomException(DELETE_FAILED);
        }
    }

    /**
     * 根据用户id获取所有文章
     *
     * @param id
     * @return
     */
    public List<Article> getAllByUserId(Long id) throws CustomException {

        // 参数校验
        if (id == null) {
            throw new CustomException(PARAMETER_VERIFICATION_FAILED);
        }

        // 用户状态校验
        if (userMapper.getUser(id) == null || userMapper.getUser(id).getDeleteState() == 1) {
            throw new CustomException(USER_NOT_EXISTS);
        }
        return articleMapper.getAllByUserId(id);
    }
}
